import { Component, OnInit, ViewChild, TemplateRef, OnDestroy } from '@angular/core'
import { Router, ActivatedRoute } from '@angular/router'
import { take } from 'rxjs/operators'
import { NzMessageService } from 'ng-zorro-antd'
import { ACLService } from '@delon/acl'

import { I18NService } from '@core'
import { DetailBaseClass } from '@shared/classes/DetailBaseClass'
import { Role, roleLevelMap } from '@shared/interfaces/role'
import { RoleService } from '../role.service'
import { PageService } from '@shared/services/page.service'
import { IDetailHeaderTab } from '@shared/interfaces/common'
import { DataService } from '@shared/services/data.service'
import { ModalService } from '@shared/services/modal.service'
import { StatusTextMap } from '@shared/interfaces/common'
import { DetailHeaderComponent } from '@shared/components/detail-header/detail-header.component'
import { roleNameMinLength, roleNameMaxLength, roleDescMaxLength } from 'app/utils/contraints'
import { Validators } from 'app/utils/validator'

@Component({
  selector: 'app-role-detail',
  templateUrl: './detail.component.html',
})
export class RoleDetailComponent extends DetailBaseClass<Role> implements OnInit, OnDestroy {
  tabs: IDetailHeaderTab[] = [
    { text: this.trans('ROLE.USER.TAB'), url: './users' },
    { text: this.trans('ROLE.PERMISSION.TAB'), url: './open-function' },
  ]

  @ViewChild('tplControl') tplControl: TemplateRef<void>

  @ViewChild(DetailHeaderComponent) detailHeaderComponent: DetailHeaderComponent

  constructor(
    public pageService: PageService,
    public aclService: ACLService,
    private i18n: I18NService,
    private router: Router,
    private route: ActivatedRoute,
    private msg: NzMessageService,
    private modalService: ModalService,
    private roleService: RoleService,
    private dataService: DataService,
  ) {
    super(pageService)
  }

  ngOnInit() {
    this.getRole()
  }

  ngOnDestroy() {
    this.pageService.triggerBaseEdit(false)
  }

  getRole(): void {
    this.loading = true
    const roleId = this.route.snapshot.params['id']
    this.roleService
      .getRoleById(roleId)
      .pipe(take(1))
      .subscribe(role => {
        this.renderRole(role)
        this.loading = false
      })
  }

  delete(roleId: string): void {
    this.modalService.delete(this.trans('GENERAL.NOTIFICATION.DELETE_CONFIRM')).subscribe(isOk => {
      if (!isOk) {
        return
      }
      this.roleService
        .deleteRole(roleId)
        .pipe(take(1))
        .subscribe(() => this.deleteSuccess(), err => this.deleteFail())
    })
  }

  copy(roleId: string): void {
    this.router.navigate([`../copy/from/${roleId}`], { relativeTo: this.route })
  }

  freeze(): void {
    const { roleId, roleName } = this.detailData
    const msg = this.trans('GENERAL.NOTIFICATION.ROLE_FREEZE_CONFIRM', { roleName })
    this.modalService
      .freezeAndUnFreeze(msg)
      .pipe(take(1))
      .subscribe(isOk => {
        if (!isOk) {
          return
        }
        this.roleService
          .freeze(roleId)
          .subscribe(
            () => this.freezeOrUnFreezeSuccess(this.trans('GENERAL.NOTIFICATION.FREEZE_SUCCESS')),
            () => this.freezeOrUnFreezeFail(this.trans('GENERAL.NOTIFICATION.UNFREEZE_FAIL')),
          )
      })
  }

  unfreeze(): void {
    const { roleId, roleName } = this.detailData
    const msg = this.trans('GENERAL.NOTIFICATION.ROLE_UNFREEZE_CONFIRM', { roleName })
    this.modalService
      .freezeAndUnFreeze(msg)
      .pipe(take(1))
      .subscribe(isOk => {
        if (!isOk) {
          return
        }
        this.roleService
          .unfreeze(roleId)
          .subscribe(
            () => this.freezeOrUnFreezeSuccess(this.trans('GENERAL.NOTIFICATION.UNFREEZE_SUCCESS')),
            err => this.freezeOrUnFreezeFail(this.trans('GENERAL.NOTIFICATION.UNFREEZE_FAIL')),
          )
      })
  }

  private freezeOrUnFreezeSuccess(message: string): void {
    this.msg.success(message)
    this.getRole()
  }

  private freezeOrUnFreezeFail(message: string): void {
    this.msg.error(message)
  }

  triggerBaseEdit(): void {
    this.copiedDetailData = this.copyDetailData(this.detailData)
    this.pageService.triggerBaseEdit(true)
  }

  cancelBase(): void {
    this.detailData = this.copiedDetailData
    this.dataService.setRole(this.detailData)
    this.clearColumnsErrorTips()
    this.initFirstColumns()
    this.initSecondColumns()
    this.initColumns()
    this.pageService.triggerBaseEdit(false)
  }

  saveBase(): void {
    if (!this.checkEditValidation()) {
      this.msg.error(this.trans('GENERAL.NOTIFICATION.VALIDATION_FAIL'))
      return
    }
    try {
      this.detailHeaderComponent.hideButtons()
      this.pageService.triggerBaseEdit(false)
      this.updateColumns()
      const { roleId, roleName, roleType, roleDesc, insCodes, menus } = this.detailData
      const data = {
        roleName,
        roleType,
        roleDesc,
        insCodes,
        menus: menus.map(m => m.menuId),
      }
      this.roleService
        .updateRole(roleId, data)
        .pipe(take(1))
        .subscribe(role => {
          this.loading = false
          const currentRole = this.dataService.role$.value
          this.dataService.setRole(Object.assign(currentRole, role))
          this.clearColumnsErrorTips()
          this.msg.success(this.trans('GENERAL.NOTIFICATION.UPDATE_SUCCESS'))
        })
    } catch (err) {
      this.msg.error(this.trans('GENERAL.NOTIFICATION.UPDATE_FAIL'), err.message)
    }
  }

  trans(key: string, params?: Object): string {
    if (!key) {
      return ''
    }
    return this.i18n.fanyi(key, params)
  }

  private deleteSuccess(): void {
    this.msg.success(this.trans('GENERAL.NOTIFICATION.DELETE_SUCCESS'))
    this.router.navigate(['../'], { relativeTo: this.route })
  }

  private deleteFail(): void {
    this.msg.error(this.trans('GENERAL.NOTIFICATION.DELETE_FAIL'))
  }

  private renderRole(role: Role): void {
    this.detailData = role
    this.dataService.setRole(role)
    this.initFirstColumns()
    this.initSecondColumns()
    this.initColumns()
  }

  private initFirstColumns(): void {
    this.firstColumns = [
      {
        span: 6,
        index: 'roleId',
        label: 'ROLE.ROLE_ID',
        labelI18n: 'ROLE.ROLE_ID',
        disEditable: true,
      },
      {
        span: 6,
        index: 'insCodes',
        label: 'ROLE.OWNER_INSTITUT ION',
        labelI18n: 'ROLE.OWNER_INSTITUTION',
        disEditable: true,
      },
      {
        span: 6,
        index: 'roleName',
        label: 'ROLE.R OLE_NAME',
        labelI18n: 'ROLE.ROLE_NAME',
        validator: {
          funcs: [
            Validators.required,
            Validators.minLength(roleNameMinLength),
            Validators.maxLength(roleNameMaxLength),
          ],
          errorTips: [
            this.trans('VALIDATION.REQUIRED', { name: this.trans('ROLE.ROLE_NAME') }),
            this.trans('VALIDATION.MAX_LENGTH', { length: roleNameMaxLength }),
          ],
        },
      },
      {
        span: 6,
        index: 'roleType',
        label: 'RO LE.ROLE_LEVEL',
        labelI18n: 'ROLE.ROLE_LEVEL',
        disEditable: true,
        displayValue: this.getRoleTypeDisplayValue(),
      },
    ]
  }

  private initSecondColumns(): void {
    this.secondColumns = [
      {
        span: 14,
        index: 'roleDesc',
        label: 'ROLE.ROLE_DESC',
        labelI18n: 'ROLE.ROLE_DESC',
        validator: {
          funcs: [Validators.required, Validators.maxLength(roleDescMaxLength)],
          errorTips: [
            this.trans('VALIDATION.REQUIRED', { name: this.trans('ROLE.ROLE_DESC') }),
            this.trans('VALIDATION.MAX_LENGTH', { length: roleDescMaxLength }),
          ],
        },
      },
      {
        span: 4,
        index: 'status',
        label: 'GENERAL.INFO.STATUS',
        labelI18n: 'GENERAL.INFO.STATUS',
        disEditable: true,
        displayValue: this.getStatusDisplayValue(),
      },
      {
        span: 6,
        operate: true,
        label: 'GENERAL.INFO.OPERATION',
        labelI18n: 'GENERAL.INFO.OPERATION',
        template: this.tplControl,
        disEditable: true,
        acl: [
          'api.put.camel.role.one.freeze',
          'api.put.camel.role.one.unfreeze',
          'api.delete.camel.role.one',
          'api.post.camel.role.one',
        ],
      },
    ]
  }

  private getRoleTypeDisplayValue(): string {
    const key = roleLevelMap[this.detailData.roleType]
    if (!key) {
      return ''
    }
    return this.trans(key)
  }

  private getStatusDisplayValue(): string {
    const key = StatusTextMap[this.detailData.status]
    if (!key) {
      console.error('status is', this.detailData.status)
      return ''
    }
    return this.trans(key)
  }
}
